using Commons.Exceptions;
using Commons.Models.OperationsContext;
using Commons.Models.Locks;
using Commons.Models.Settings;
using System.Collections.Generic;

namespace Commons.Services.Locks
{
	public class LockService : ILockService
	{
		public IDictionary<string, IUnlockConditionChecker> Checkers { get; set; }
        public List<int> UnlockIds; 

		public bool CheckLock(Lock lockObject)
		{
			return CheckLock(lockObject, null);
		}

		public bool CheckLock(Lock lockObject, IOperationContext context)
		{
			if (lockObject == null)
			{
				return true;
			}

			if (UnlockIds.Contains(lockObject.Id))
			{
				return true;
			}

			ICollection<IUnlockCondition> conditions = lockObject.UnlockConditions;
			if (conditions.Count == 0)
			{
				return false;
			}

			foreach (IUnlockCondition condition in conditions)
			{
				IUnlockConditionChecker checker;
				if (!Checkers.TryGetValue(condition.Type, out checker))
				{
					throw new KeyNotFoundException("CHECKER ID DOES NOT EXIST=" + condition.Type);
				}
				if (!checker.CheckCondition(condition, context))
				{
					return false;
				}
			}

			return true;
		}

		public void ValidateLock(Lock lockObject, object obj, object action)
		{
			ValidateLock(lockObject, obj, action, null);
		}

		public void ValidateLock(Lock lockObject, object obj, object action, IOperationContext context)
		{
			if (!CheckLock(lockObject, context))
			{
				throw new LockException("Can not execute " + action + " on " + obj + " because is locked by " + lockObject);
			}
		}

		public ICollection<int> GetEarlyUnlocks()
		{
			return UnlockIds;
		}

		public void Unlock(int lockId)
		{
			if (lockId == Lock.PublicId)
			{
				throw new LockException("Public lock can't be unlocked");
			}
            UnlockIds.Add(lockId);
		}

		public Lock GetLock(int lockId)
		{
			LockSettings lockSettings = SettingsModel.Instance.GetSettings<LockSettings>();

			return lockSettings.GetLock(lockId);
		}
	}
}

